package model.item; 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import model.entity.BasicEntity;
import model.entity.Entity;
import model.entity.stats.DerivedStat;
import model.entity.stats.Stat;
import model.entity.stats.StatSet;
import model.skill.Skill;
import utilities.*;

public class Condition implements Archiveable {

	private StatSet requiredStats;
	private List<Skill> requiredSkills;
	private List<Item> requiredItems;
	
	public Condition()
	{
		requiredStats = null;
		requiredSkills = null;
		requiredItems = null;
	}
	
	public Condition(StatSet requiredStats, List<Skill> requiredSkills, List<Item> requiredItems)
	{
		this.requiredStats = requiredStats;
		this.requiredSkills = requiredSkills;
		this.requiredItems = requiredItems;
	}
	
	public boolean meetsRequirements(Entity entity)
	{
		boolean passed = false;
		
		/*
		 * The lovely Stat check. Viola.
		 */
		StatSet entityStatSet = entity.getStats();
		Map<String, Stat> requiredStatss = requiredStats.getStats();
		Map<String, DerivedStat> requiredDerivedStats = requiredStats.getDerivedStats();
		
		Map<String, Stat> entityStats = entityStatSet.getStats();
		Map<String, DerivedStat> entityDerivedStats = entityStatSet.getDerivedStats(); 
		
		Set<String> statList = requiredStatss.keySet();
		Set<String> derivedStatList = requiredDerivedStats.keySet();
		
		Iterator<String> statIt = statList.iterator();
		Iterator<String> derivedStatIt = derivedStatList.iterator();
		
		Stat requiredStat;
		Stat entityStat;
		DerivedStat requiredDerivedStat;
		DerivedStat entityDerivedStat;
		
		while(statIt.hasNext())
		{
			String stat= statIt.next();
			if(entityStats.containsKey(stat))
			{
				requiredStat = requiredStatss.get(stat);
				entityStat = entityStats.get(stat);
				if(entityStat.getValue() < requiredStat.getValue())
					return passed;
				else
					;
			}
			else
				return passed;
		}
		
		while(derivedStatIt.hasNext())
		{
			String derivedStat = derivedStatIt.next();
			if(entityDerivedStats.containsKey(derivedStat))
			{
				requiredDerivedStat = requiredDerivedStats.get(derivedStat);
				entityDerivedStat = entityDerivedStats.get(derivedStat);
				if(entityDerivedStat.getValue() < requiredDerivedStat.getValue())
					return passed;
				else
					;
			}
			else
				return passed;
		}
		
		/*
		 * Skill check
		 */
		
		List<Skill> entitySkillList = entity.getOccupation().getAllowableSkills();
		Iterator<Skill> requiredSkillIt = requiredSkills.iterator();
		while(requiredSkillIt.hasNext())
		{
			Skill requiredSkillCheck= requiredSkillIt.next();
			if(entitySkillList.contains(requiredSkillCheck))
				;
			else
				return passed;
		}
		
		/*
		 * Item check
		 */
		
		List<TakeableItem> entityInventory = entity.getInventoryItems();
		Iterator<Item> requiredItemIt = requiredItems.iterator();
		while(requiredItemIt.hasNext())
		{
			Item requiredItem = requiredItemIt.next();
			if(entityInventory.contains(requiredItem))
				;
			else
				return passed;
		}
		
		passed = true;
		return passed;
	}
	
	public Archive save() {
		Archive archive = ArchiveFactory.createArchive();
		
		archive.putClassName("requiredStats", this.requiredStats.getClass().getName());
		archive.putOneRelationship("requiredStats", this.requiredStats);
		
		List<String> requiredItemsClassList = new ArrayList<String>();
		for (int i = 0; i < this.requiredItems.size(); i++) {
			requiredItemsClassList.add(this.requiredItems.get(i).getClass().getName());
		}
		archive.putAttributeList("requiredItemsClassList", requiredItemsClassList);
		archive.putManyRelationship("requiredItems", this.requiredItems);
		
		List<String> requiredSkillsClassList = new ArrayList<String>();
		for (int i = 0; i < this.requiredSkills.size(); i++) {
			requiredSkillsClassList.add(this.requiredSkills.get(i).getClass().getName());
		}
		archive.putAttributeList("requiredSkillsClassList", requiredSkillsClassList);
		archive.putManyRelationship("requiredSkills", this.requiredSkills);
		
		return archive;
	}
	
	public void load(Archive archive) {
		this.requiredStats = (StatSet)ModelFactory.getInstance().createInstanceWithClassName(archive.getClassName("requiredStats"));
		this.requiredStats.load(archive.getOneRelationship("requiredStats"));
		
		List<String> requiredItemsClassList = archive.getAttributeList("requiredItems");
		List<Archive> requiredItemsArchives = archive.getManyRelationship("requiredItems");
		this.requiredItems = new ArrayList<Item>();
		for (int i = 0; i < requiredItemsClassList.size(); i++) {
			Item item = (Item)ModelFactory.getInstance().createInstanceWithClassName(requiredItemsClassList.get(i));
			item.load(requiredItemsArchives.get(i));
			this.requiredItems.add(item);
		}
		
		List<String> requiredSkillsClassList = archive.getAttributeList("requiredSkills");
		List<Archive> requiredSkillsArchives = archive.getManyRelationship("requiredSkills");
		this.requiredSkills = new ArrayList<Skill>();
		for (int i = 0; i < requiredItemsClassList.size(); i++) {
			Skill skill = (Skill)ModelFactory.getInstance().createInstanceWithClassName(requiredSkillsClassList.get(i));
			skill.load(requiredSkillsArchives.get(i));
			this.requiredSkills.add(skill);
		}
	}
}
